#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
浏览器管理模块
负责浏览器的初始化、配置和关闭
"""

import sys
import platform
import subprocess
import time
import traceback
import os
import zipfile
import shutil
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

# 可选导入
try:
    import requests
    HAS_REQUESTS = True
except ImportError:
    HAS_REQUESTS = False
    print("警告: 未找到requests库，手动下载功能将不可用")

class BrowserManager:
    """浏览器管理类，处理浏览器的初始化和关闭"""
    
    def __init__(self, headless=False, debug=False):
        """初始化浏览器管理器
        
        Args:
            headless: 是否使用无头模式（不显示浏览器界面）
            debug: 是否启用调试模式
        """
        self.headless = headless
        self.debug = debug
        self.driver = None
    
    def initialize_browser(self):
        """初始化浏览器并返回WebDriver实例
        
        Returns:
            WebDriver: 初始化好的WebDriver实例
        """
        try:
            print("\n正在初始化Chrome浏览器...")
            
            # 创建Chrome浏览器选项
            options = webdriver.ChromeOptions()
            
            # 根据设置决定是否使用无头模式
            if self.headless:
                options.add_argument('--headless')
            
            # 设置通用选项
            options.add_argument('--no-sandbox')
            options.add_argument('--disable-dev-shm-usage')
            options.add_argument('--disable-popup-blocking')  # 禁用弹出窗口拦截
            options.add_argument('--disable-extensions')  # 禁用扩展
            options.add_argument('--disable-notifications')  # 禁用通知
            
            # 设置下载相关选项
            # 获取当前目录作为下载目录
            current_dir = os.getcwd()
            download_dir = os.path.join(current_dir, "downloads")
            
            # 确保下载目录存在
            if not os.path.exists(download_dir):
                os.makedirs(download_dir)
                
            print(f"设置下载目录: {download_dir}")
            
            # 设置下载偏好，特别优化蓝奏云下载
            prefs = {
                # 禁用"保存密码"提示
                "credentials_enable_service": False,
                "profile.password_manager_enabled": False,
                
                # 下载设置
                "download.default_directory": download_dir,
                "download.prompt_for_download": False,  # 不要提示下载
                "download.directory_upgrade": True,     # 允许升级下载目录
                "safebrowsing.enabled": False,          # 禁用安全浏览，避免被拦截
                "plugins.always_open_pdf_externally": True,  # PDF文件不在浏览器中打开
                
                # 蓝奏云特定设置
                "profile.default_content_settings.popups": 0,  # 允许弹出窗口
                "profile.default_content_setting_values.automatic_downloads": 1,  # 允许多个文件自动下载
                
                # 下载类型处理 - 对于特定MIME类型直接下载而不是打开
                "download.default_content_setting_values.cookies": 1,  # 接受所有cookie
                "download.extensions_to_open": "",
                "download.open_pdf_in_system_reader": False,  # 不用系统PDF阅读器打开PDF
                
                # 媒体设置
                "profile.managed_default_content_settings.images": 1,  # 加载图片
                
                # 增强蓝奏云下载
                "profile.content_settings.exceptions.automatic_downloads.*.setting": 1,
                "download.prompt_for_download": False,
                "download.restrictions": 0,  # 关闭下载限制
                
                # MIME类型处理
                "download.default_content_setting_values": {
                    "automatic_downloads": 1,
                    "cookies": 1
                },
                
                # 跨源请求
                "profile.default_content_setting_values.cross_origin_downloads": 1,
                
                # 网络设置
                "network.cookie_enabled": True,
                "profile.cookie_controls_mode": 0,  # 允许所有cookie
            }
            options.add_experimental_option("prefs", prefs)
            
            # 添加其他必要的参数
            options.add_argument("--disable-blink-features=AutomationControlled")  # 隐藏自动化控制
            options.add_experimental_option("excludeSwitches", ["enable-automation", "enable-logging"])
            options.add_experimental_option("useAutomationExtension", False)
            
            # 处理ssl证书问题
            options.add_argument('--ignore-ssl-errors=yes')
            options.add_argument('--ignore-certificate-errors')
            options.add_argument('--allow-insecure-localhost')
            
            # 启用跨域
            options.add_argument('--disable-web-security')
            options.add_argument('--allow-running-insecure-content')
            options.add_argument('--allow-file-access-from-files')
            
            # 提升性能
            options.add_argument('--disable-gpu')
            options.add_argument('--disable-features=VizDisplayCompositor')
            options.add_argument('--disable-features=NetworkPrediction')
            
            # 添加UA头，模拟普通用户
            options.add_argument("user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
            
            # 定义多种初始化方法，按优先级顺序尝试
            init_methods = [
                ("Direct Chrome", self._init_method_direct),
                ("Service", self._init_method_service),
                ("Default Path", self._init_method_default_path),
                ("ChromeDriverManager", self._init_method_webdriver_manager),
                ("Manual Download", self._init_method_manual_download),
            ]
            
            # 逐一尝试初始化方法
            for method_name, method_func in init_methods:
                try:
                    print(f"\n正在尝试方法: {method_name}")
                    self.driver = method_func(options)
                    
                    # 如果成功创建了driver，跳出循环
                    if self.driver:
                        print(f"使用 {method_name} 方法成功初始化Chrome浏览器！")
                        break
                        
                except Exception as e:
                    print(f"方法 {method_name} 失败: {str(e)}")
                    if self.debug:
                        traceback.print_exc()
                    continue
            
            # 如果所有方法都失败了
            if not self.driver:
                print("所有初始化方法都失败了，无法启动Chrome浏览器")
                self._show_chromedriver_installation_guide()
                return None
            
            # 设置浏览器窗口大小
            self.driver.set_window_size(1280, 800)
            
            # 设置页面加载超时
            self.driver.set_page_load_timeout(120)  # 增加超时时间
            
            # 设置脚本执行超时
            self.driver.set_script_timeout(120)  # 增加超时时间
            
            # 执行JS脚本以避免被网站识别为自动化工具
            self.driver.execute_script("Object.defineProperty(navigator, 'webdriver', {get: () => undefined})")
            
            # 设置更多的特定于蓝奏云的参数
            self.driver.execute_script("""
                Object.defineProperty(navigator, 'languages', {
                    get: function() {
                        return ['zh-CN', 'zh', 'en-US', 'en'];
                    }
                });
                
                Object.defineProperty(navigator, 'plugins', {
                    get: function() {
                        return [1, 2, 3, 4, 5];
                    }
                });
                
                // 增加指纹模拟
                Object.defineProperty(navigator, 'platform', {
                    get: function() {
                        return 'Win32';
                    }
                });
                
                // 修改canvas指纹
                const originalGetContext = HTMLCanvasElement.prototype.getContext;
                HTMLCanvasElement.prototype.getContext = function(type) {
                    const context = originalGetContext.apply(this, arguments);
                    if (type === '2d') {
                        const originalFillText = context.fillText;
                        context.fillText = function() {
                            return originalFillText.apply(this, arguments);
                        };
                    }
                    return context;
                };
            """)
            
            print("Chrome浏览器初始化成功！")
            
            # 返回WebDriver实例
            return self.driver
            
        except Exception as e:
            print(f"浏览器初始化失败: {str(e)}")
            traceback.print_exc()
            return None
    
    def close_browser(self):
        """关闭浏览器实例"""
        if hasattr(self, 'driver') and self.driver:
            try:
                print("\n正在关闭浏览器...")
                self.driver.quit()
                print("浏览器已关闭")
            except Exception as e:
                print(f"关闭浏览器时出错: {str(e)}")
                
    def safe_get(self, url, retry_count=3):
        """安全地访问URL，包含重试机制
        
        Args:
            url: 要访问的URL
            retry_count: 重试次数
            
        Returns:
            bool: 是否成功访问
        """
        for attempt in range(retry_count):
            try:
                self.driver.get(url)
                time.sleep(2)  # 等待页面加载
                return True
            except Exception as e:
                print(f"访问URL失败 (尝试 {attempt+1}/{retry_count}): {str(e)}")
                if attempt < retry_count - 1:
                    print("正在重试...")
                    time.sleep(2)
                else:
                    print("达到最大重试次数，放弃尝试")
                    return False
        return False
    
    def _init_method_direct(self, options):
        """方法1: 直接初始化Chrome"""
        print("\n正在直接初始化Chrome浏览器...")
        
        # 首先尝试使用明确的chromedriver路径，避免Selenium使用SeleniumManager
        chromedriver_path = "/opt/homebrew/bin/chromedriver"
        if os.path.exists(chromedriver_path) and os.access(chromedriver_path, os.X_OK):
            try:
                print(f"使用明确路径: {chromedriver_path}")
                service = Service(chromedriver_path)
                return webdriver.Chrome(service=service, options=options)
            except Exception as e:
                print(f"明确路径失败: {str(e)}")
        
        # 尝试在系统PATH中查找chromedriver
        try:
            # 首先尝试直接使用系统PATH中的chromedriver
            return webdriver.Chrome(options=options)
        except Exception as e1:
            print(f"系统PATH中未找到chromedriver: {str(e1)}")
            
            # 尝试在一些常见路径中查找chromedriver
            possible_paths = []
            
            if platform.system() == "Darwin":  # macOS
                possible_paths = [
                    "/usr/local/bin/chromedriver",
                    "/opt/homebrew/bin/chromedriver",
                    "/usr/bin/chromedriver",
                    os.path.expanduser("~/bin/chromedriver"),
                ]
            elif platform.system() == "Windows":
                possible_paths = [
                    "C:\\Program Files\\Google\\Chrome\\Application\\chromedriver.exe",
                    "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe",
                    "C:\\chromedriver.exe",
                    os.path.expanduser("~\\chromedriver.exe"),
                ]
            else:  # Linux
                possible_paths = [
                    "/usr/local/bin/chromedriver",
                    "/usr/bin/chromedriver",
                    "/bin/chromedriver",
                    os.path.expanduser("~/bin/chromedriver"),
                ]
            
            # 尝试每个可能的路径
            for path in possible_paths:
                if os.path.exists(path) and os.access(path, os.X_OK):
                    try:
                        print(f"找到ChromeDriver: {path}")
                        service = Service(path)
                        return webdriver.Chrome(service=service, options=options)
                    except Exception as e2:
                        print(f"路径 {path} 无效: {str(e2)}")
                        continue
            
            # 如果所有尝试都失败了
            raise Exception("无法找到有效的chromedriver")
    
    def _init_method_service(self, options):
        """方法2: 使用Service初始化"""
        print("\n尝试使用Service初始化Chrome浏览器...")
        service = Service()
        return webdriver.Chrome(service=service, options=options)
    
    def _init_method_webdriver_manager(self, options):
        """方法3: 使用ChromeDriverManager"""
        print("\n尝试使用ChromeDriverManager初始化Chrome浏览器...")
        from webdriver_manager.chrome import ChromeDriverManager
        
        # 使用webdriver-manager自动下载和管理ChromeDriver
        print("正在下载/更新ChromeDriver...")
        driver_path = ChromeDriverManager().install()
        
        # 修复webdriver-manager在macOS上可能返回错误路径的问题
        if platform.system() == "Darwin":
            # 检查返回的路径是否指向正确的chromedriver文件
            if not driver_path.endswith('chromedriver') or 'THIRD_PARTY_NOTICES' in driver_path:
                # 在macOS上，确保使用正确的chromedriver文件
                driver_dir = os.path.dirname(driver_path)
                actual_driver_path = os.path.join(driver_dir, 'chromedriver')
                if os.path.exists(actual_driver_path):
                    driver_path = actual_driver_path
                    print(f"修正ChromeDriver路径: {driver_path}")
            
            # 确保chromedriver有执行权限
            if os.path.exists(driver_path):
                os.chmod(driver_path, 0o755)
                print(f"设置ChromeDriver执行权限: {driver_path}")
        
        service = Service(driver_path)
        return webdriver.Chrome(service=service, options=options)
    
    def _init_method_default_path(self, options):
        """方法4: 使用默认的Chrome路径"""
        print("\n尝试使用默认的Chrome路径")
        
        if platform.system() == "Darwin":  # macOS
            default_chrome = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
        elif platform.system() == "Windows":
            default_chrome = "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe"
        else:  # Linux
            default_chrome = "/usr/bin/google-chrome"
        
        options.binary_location = default_chrome
        return webdriver.Chrome(options=options)
    
    def _download_chromedriver_manual(self):
        """手动下载ChromeDriver（不使用SSL验证）"""
        if not HAS_REQUESTS:
            print("缺少requests库，无法使用手动下载功能")
            return None
            
        try:
            print("正在手动下载ChromeDriver...")
            
            # 获取Chrome版本
            chrome_version = self._get_chrome_version()
            if not chrome_version:
                print("无法获取Chrome版本，使用默认版本")
                chrome_version = "119.0.6045.105"  # 使用一个稳定版本
            
            # 下载目录
            download_dir = os.path.join(os.path.expanduser("~"), ".chromedriver")
            if not os.path.exists(download_dir):
                os.makedirs(download_dir)
            
            # 根据系统选择下载URL
            if platform.system() == "Darwin":  # macOS
                if platform.machine() == "arm64":
                    url = f"https://storage.googleapis.com/chrome-for-testing-public/{chrome_version}/mac-arm64/chromedriver-mac-arm64.zip"
                else:
                    url = f"https://storage.googleapis.com/chrome-for-testing-public/{chrome_version}/mac-x64/chromedriver-mac-x64.zip"
            elif platform.system() == "Windows":
                url = f"https://storage.googleapis.com/chrome-for-testing-public/{chrome_version}/win64/chromedriver-win64.zip"
            else:  # Linux
                url = f"https://storage.googleapis.com/chrome-for-testing-public/{chrome_version}/linux64/chromedriver-linux64.zip"
            
            # 下载文件
            zip_path = os.path.join(download_dir, "chromedriver.zip")
            
            # 禁用SSL验证下载
            response = requests.get(url, verify=False, timeout=30)
            response.raise_for_status()
            
            with open(zip_path, "wb") as f:
                f.write(response.content)
            
            print(f"ChromeDriver下载完成: {zip_path}")
            
            # 解压文件
            with zipfile.ZipFile(zip_path, 'r') as zip_ref:
                zip_ref.extractall(download_dir)
            
            # 查找chromedriver文件
            chromedriver_path = None
            for root, dirs, files in os.walk(download_dir):
                for file in files:
                    if file == "chromedriver" or file == "chromedriver.exe":
                        chromedriver_path = os.path.join(root, file)
                        break
                if chromedriver_path:
                    break
            
            if chromedriver_path:
                # 设置执行权限
                os.chmod(chromedriver_path, 0o755)
                print(f"ChromeDriver已准备就绪: {chromedriver_path}")
                
                # 清理下载文件
                os.remove(zip_path)
                
                return chromedriver_path
            else:
                print("解压后未找到chromedriver文件")
                return None
                
        except Exception as e:
            print(f"手动下载ChromeDriver失败: {str(e)}")
            return None
    
    def _get_chrome_version(self):
        """获取Chrome版本"""
        try:
            if platform.system() == "Darwin":  # macOS
                result = subprocess.run([
                    "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
                    "--version"
                ], capture_output=True, text=True, timeout=10)
            elif platform.system() == "Windows":
                result = subprocess.run([
                    "C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
                    "--version"
                ], capture_output=True, text=True, timeout=10)
            else:  # Linux
                result = subprocess.run([
                    "google-chrome", "--version"
                ], capture_output=True, text=True, timeout=10)
            
            if result.returncode == 0:
                version = result.stdout.strip().split()[-1]
                print(f"检测到Chrome版本: {version}")
                return version
            
        except Exception as e:
            print(f"无法获取Chrome版本: {str(e)}")
        
        return None
    
    def _init_method_manual_download(self, options):
        """方法5: 手动下载ChromeDriver"""
        print("\n尝试手动下载ChromeDriver...")
        
        chromedriver_path = self._download_chromedriver_manual()
        if chromedriver_path:
            service = Service(chromedriver_path)
            return webdriver.Chrome(service=service, options=options)
        else:
            raise Exception("手动下载ChromeDriver失败")
    
    def _show_chromedriver_installation_guide(self):
        """显示ChromeDriver安装指导"""
        print("\n" + "="*60)
        print("ChromeDriver安装指导")
        print("="*60)
        
        if platform.system() == "Darwin":  # macOS
            print("对于macOS系统，您可以使用以下方法安装ChromeDriver:")
            print("1. 使用Homebrew安装:")
            print("   brew install chromedriver")
            print("\n2. 手动下载:")
            print("   - 访问: https://sites.google.com/chromium.org/driver/")
            print("   - 下载适合您Chrome版本的ChromeDriver")
            print("   - 解压后放到 /usr/local/bin/ 目录")
            print("   - 运行: chmod +x /usr/local/bin/chromedriver")
            
        elif platform.system() == "Windows":
            print("对于Windows系统，您可以使用以下方法安装ChromeDriver:")
            print("1. 手动下载:")
            print("   - 访问: https://sites.google.com/chromium.org/driver/")
            print("   - 下载适合您Chrome版本的ChromeDriver")
            print("   - 解压后放到系统PATH目录中")
            print("   - 或者放到Chrome安装目录")
            
        else:  # Linux
            print("对于Linux系统，您可以使用以下方法安装ChromeDriver:")
            print("1. 使用包管理器:")
            print("   sudo apt-get install chromium-chromedriver  # Ubuntu/Debian")
            print("   sudo yum install chromedriver  # CentOS/RHEL")
            print("\n2. 手动下载:")
            print("   - 访问: https://sites.google.com/chromium.org/driver/")
            print("   - 下载适合您Chrome版本的ChromeDriver")
            print("   - 解压后放到 /usr/local/bin/ 目录")
            print("   - 运行: chmod +x /usr/local/bin/chromedriver")
        
        print("\n" + "="*60)
        print("安装完成后，请重新运行程序。")
        print("="*60) 